﻿namespace MicroCloud.Audit
{
    /// <summary>
    /// 数据库审计存储
    /// </summary>
    public class AuditHandler : IAuditHandler
    {
        //字段
        private readonly IRepository<AuditOperation, long> _operationRepository;

        /// <summary>
        /// 初始化一个数据库审计存储 <see cref="AuditHandler"/> 的新实例
        /// </summary>
        /// <param name="operationRepository"></param>
        public AuditHandler(IRepository<AuditOperation, long> operationRepository)
        {
            _operationRepository = operationRepository;
        }

        #region IAuditStore
        /// <summary>
        /// 设置保存审计数据
        /// </summary>
        /// <param name="operationEntry">操作审计数据</param>
        public void Save(AuditOperationEntry operationEntry)
        {
            AuditOperation operation = BuildOperation(operationEntry);
            _operationRepository.Insert(operation);
        }
        
        /// <summary>
        /// 异步保存实体审计数据
        /// </summary>
        /// <param name="operationEntry">操作审计数据</param>
        /// <param name="cancelToken">异步取消标识</param>
        /// <returns></returns>
        public async Task SaveAsync(AuditOperationEntry operationEntry, CancellationToken cancelToken = default)
        {
            AuditOperation operation = BuildOperation(operationEntry);
            await _operationRepository.InsertAsync(operation);
        }

        #endregion

        #region 私有方法
        /// <summary>
        /// 构建操作
        /// </summary>
        /// <param name="operationEntry">审计操作信息</param>
        /// <returns></returns>
        private static AuditOperation BuildOperation(AuditOperationEntry operationEntry)
        {
            AuditOperation operation = operationEntry.MapTo<AuditOperationEntry, AuditOperation>();
            if (operationEntry.UserAgent != null)
            {
                UserAgent userAgent = new(operationEntry.UserAgent);
                operation.OperationSystem = userAgent.GetSystem();
                operation.Browser = userAgent.GetBrowser();
            }
            operation.Elapsed = (int)operationEntry.EndedTime.Subtract(operationEntry.CreatedTime).TotalMilliseconds;
            if (operation.ResultType == AjaxResultType.Success)
            {
                foreach (AuditEntityEntry entityEntry in operationEntry.EntityEntries)
                {
                    AuditEntity entity = entityEntry.MapTo<AuditEntityEntry, AuditEntity>();
                    operation.AuditEntities.Add(entity);
                    foreach (AuditPropertyEntry propertyEntry in entityEntry.PropertyEntries)
                    {
                        AuditProperty property = propertyEntry.MapTo<AuditPropertyEntry, AuditProperty>();
                        entity.Properties.Add(property);
                    }
                }
            }
            return operation;
        }

        #endregion

    }

}